#include "IA_Robot.h"

#include "PathMap.hpp"

IA_Robot::IA_Robot(Landscape carte, long ordre)
{
    msg.push_back("");
    m_carte = carte;
    canChangeDest = true;
    // Remplire les piles
    
    mPathMap = new PathMap;
    QVector<int> map;
    for(int i = 0; i < m_carte.cases.size(); i++){
    		for(int j = 0; j < m_carte.cases.at(i).size(); j++){
    				map.push_back(m_carte.cases[i][j]);
    		}
    }
    mPathMap.fillMap(map, m_carte.cases.size(), m_carte.cases.at(0).size());
}

RetR IA_Robot::process(D4R data)
{
    // Actualisation
    m_position = data.m_position;
    m_pv = data.m_health_point;
    m_energie = data.m_energy;
    m_soute = data.m_cargo;

    // FAIRE LA RÉCEPTION DES SIGNAUX !

    // Analyse du champs de vision
    switch(m_type)
    {
        case PEON: // Récolter ressources & technologie
        case PEONVOLANT:
            actionPeon(&data);
            break;
        case JAPONAIS: // Il colle les unités ennemies et si aucune unités allié à coté -> BOUM
            break;
        case CHINOIS: // Cherche ennemis et tape
        case CHINOISVOLANT:
        case CAC:
            break;
        case EXPLORATEUR: // à voir
        case EXPLORATEURVOLANT:
            break;
        case RADIO: // Fait le relais, communique les infos qu'il voie à la base
            break;
        case ARCHER: // Tire sur l'ennemi a distance, recule si l'énnemie avance et vice-versa.
        case ARCHERVOLANT:
            break;
        default: // Si aucun type action par défaut
            break;
    }

    return m_retour;
}

void IA_Robot::actionPeon(D4R const& data)
{
    if(m_soute.m_item_list.size() == m_soute.size())
    {
        if(canChangeDest)
        {
            allerA(path(/*-POSITION NOTRE USINE-*/));
            canChangeDest = false;
            retour(A_move, 0, m_pileDeplacement.pop(), msg);
            return;
        }
    }


    QVector<M_Position> points = path(data.m_sight[0].m_position);
    int i_minLenght = 0, length = points.size();
    bool hasTechno = false;

    for(int i = 0 ; i < data.m_sight.size() ; i++)
    {
        if(data.m_sight[i].m_item == TECHNOLOGIE) // Si la destination n'est pas la case regardée actuellement
        {
            hasTechno = true;
            points = path(data.m_sight[i].m_position);
            if(points.size() < length)
            {
                length = points.size();
                i_minLenght = i;
            }
        }
    }

    if(m_pileDestination.top() != data.m_sight[i_minLenght].m_position)
    {
        if(hasTechno)
        {
            points = path(data.m_sight[i_minLenght].m_position);
            if(points.size() < m_pileDeplacement.size())
            {
                allerA(points);
            }
        }
    }
    else // Si la case regardée est la destination
    {
        if(m_pileDeplacement.size() == 1) // et si on y ai arrivé
        {
            std::vector<std::string> msg("");
            retour(A_get_item, 0, m_pileDestination.pop(), msg);
            return;
        }
    }

    if(!m_pileDeplacement.isEmpty())
    {
        retour(A_move, 0, m_pileDeplacement.pop(), msg);
        return;
    }
    else
    {
        canChangeDest = true;
        if(!m_pileDestination.isEmpty()) allerA(m_pileDestination.pop());
    }

    retour(A_wait, 0, m_position, msg); // Au cas où on n'a rien fait précédemment
    return;
}

void IA_Robot::retour(long action, long cible, M_Position pos, std::vector<std::string> msg)
{
    m_retour.id_action = action;
    m_retour.id_target = cible;
    m_retour.msg_content = PacketManager::encode(msg, cible);
    m_retour.target_position = pos;
}

void IA_Robot::allerA(QVector<M_Position> points)
{
    m_pileDeplacement.clear();

    for(int i = points.size() - 1 ; i >= 0 ; i--)
    {
        m_pileDeplacement.push(points[i]);
    }
}

QVector<M_Position> IA_Robot::path(M_Position pos)
{
		std::vector< void* > pathF;
    float totalCost;

    mMicroPather = new micropather::MicroPather(mPathMap);

    int res = mMicroPather->Solve((void*)(m_position.m_y*m_carte.cases.size() + m_position.m_x),
                                  (void*)(pos.m_y*m_carte.cases.size() + pos.m_x),
                                  &pathF,
                                  &totalCost);
                                  
    QVector<M_Position> ret;
    ret << m_position;
    //SOLVED, NO_SOLUTION, or START_END_SAME.
    switch(res){
        case micropather::MicroPather::SOLVED:
        break;

        case micropather::MicroPather::NO_SOLUTION:

        case micropather::MicroPather::START_END_SAME:
        		return ret;
        break;
    }

    int xx, yy;
    M_Position mos;

    if(res == micropather::MicroPather::SOLVED){
        for(unsigned int i = 0; i < pathF.size(); i++){
            mPathMap->NodeToXY(pathF.at(i), &xx, &yy);/** IL SE PEUT QUE XX ET YY SOIENT INVERSES **/
            mos.m_x = xx;
            mos.m_y = yy;
            ret << mos;
        }
    }
}

